import {
  RouteRegisterOptions,
  RouterHandler,
  RouterRequestWrapper,
  RouterResponse,
  RouterResponseError
} from './RouterDefine'

/**
 * 服务路由自动注册装饰器。
 * @param options 参数
 */
export function Route<T extends { new(...args: any[]): ServiceRoute }>(options: RouteRegisterOptions) {
  return function (target: T) {
    let item = RouterManagerForService.getInstance().registeMap[options.routeName]
    if (item == undefined) {
      RouterManagerForService.getInstance().registeRoute(options.routeName, { routeName: options.routeName })
    }
    let ele = new target()
    RouterManagerForService.getInstance().registeMap[options["routeName"]].element ??= ele
  };
}

export type SuccessCallback = (data: object | string) => void

export type ErrorCallback = (code: number, msg: string) => void

/**
 * 服务路由基类。定义服务路由时需要继承该类。
 */
export abstract class ServiceRoute {
  abstract onAction(pageInstance: ESObject, params: Record<string, ESObject>, callback: SuccessCallback, errorCallback?: ErrorCallback)
}

/**
 * 服务路由管理类持有的参数。
 */
export interface RouteItem {
  routeName: string,
  element?: ServiceRoute
}

/**
 * 服务路由管理类。
 */
export class RouterManagerForService implements RouterHandler {
  private static sInstance: RouterManagerForService

  public static getInstance(): RouterManagerForService {
    if (!RouterManagerForService.sInstance) {
      RouterManagerForService.sInstance = new RouterManagerForService()
    }
    return RouterManagerForService.sInstance
  }

  /* 路由注册相关方法 */

  registeMap: Map<string, RouteItem> = new Map();

  registeRoute(pageName: string, service: RouteItem) {
    this.registeMap[pageName] = service
  }

  open(request: RouterRequestWrapper): Promise<RouterResponse> {
    return new Promise((resolve, reject) => {
      let routeItem: RouteItem = RouterManagerForService.getInstance().registeMap[request.routeName];
      if (routeItem && routeItem.element) {
        // 调用服务路由实现
        routeItem.element?.onAction(request.rawRequest.pageInstance, request.params, (data) => {
          resolve({ code: RouterResponseError.Success.code, msg: RouterResponseError.Success.msg, data: data })
        }, (code, message) => {
          resolve({ code: code, msg: message })
        })
      } else {
        resolve({
          code: RouterResponseError.RequestNotFoundResponsor.code,
          msg: RouterResponseError.RequestNotFoundResponsor.msg
        })
      }
    })
  }
}